﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace Sofire.DataComm.Net.Async
{
    internal sealed class SocketAsyncEventArgsPool
    {
        Stack<SocketAsyncEventArgsServer> pool;
        EventHandler<SocketAsyncEventArgs> completed;
        AsyncSocketServer _socketServer;

        public SocketAsyncEventArgsPool(AsyncSocketServer socketServer, Int32 capacity, EventHandler<SocketAsyncEventArgs> completed)
        {
            this.pool = new Stack<SocketAsyncEventArgsServer>(capacity);
            this.completed = completed;
            this._socketServer = socketServer;
            for(int i = 0 ; i < capacity ; i++)
            {
                this.pool.Push(this.Create());
            }
        }

        private SocketAsyncEventArgsServer Create()
        {
            SocketAsyncEventArgsServer e = new SocketAsyncEventArgsServer(this._socketServer);
            e.BufferHandler = new ReceiveTranslater(this._socketServer);
            e.Completed += this.completed;
            e.SendAsyncEventArgs.Completed += this.completed;
            return e;
        }

        public Int32 Count
        {
            get
            {
                lock(this.pool)
                {
                    return this.pool.Count;
                }
            }
        }

        public SocketAsyncEventArgsServer Pop()
        {
            lock(this.pool)
            {
                if(this.pool.Count == 0) return this.Create();
                return this.pool.Pop();
            }
        }

        public void Push(SocketAsyncEventArgsServer item)
        {
            if(item == null)
            {
                throw new ArgumentNullException("item");
            }

            item.ClientInfo.RejectClient();

            if(item.RaiseReceiveEventArgs != null) item.RaiseReceiveEventArgs.Clear();

            item.SetBuffer(null, 0, 0);
            item.AcceptSocket = null;
            item.UserToken = null;
            item.IsBusy = false;

            /* 增加以下代码，避免缓存启用时引起的 BUG */
            item.RaiseReceiveEventArgs.Tag = null;
            item.RaiseSendEventArgs.Tag = null;
            /* 增加以上代码，避免缓存启用时引起的 BUG */

            item.SendAsyncEventArgs.AcceptSocket = null;
            item.SendAsyncEventArgs.SetBuffer(null, 0, 0);
            item.SendAsyncEventArgs.UserToken = null;
            item.SendAsyncEventArgs.IsBusy = false;
            item.SendAsyncEventArgs.Set();

            lock(this.pool)
            {
                this.pool.Push(item);
            }
        }
    }
}
